home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------*/
- /* */
- /* THREAD.CPP */
- /* */
- /* Copyright (c) 1993, 1994 Borland International */
- /* All Rights Reserved */
- /* */
- /*------------------------------------------------------------------------*/
-
- #if !defined( __PROCESS_H )
- #include <process.h>
- #endif
-
- #if !defined( __STDLIB_H )
- #include <stdlib.h>
- #endif
-
- #if !defined( __CHECKS_H )
- #include <checks.h>
- #endif
-
- #if !defined( CLASSLIB_DEFS_H )
- #include <classlib/defs.h>
- #endif
-
- #if !defined( CLASSLIB_THREAD_H )
- #include <classlib/thread.h>
- #endif
-
- DIAG_DEFINE_GROUP(Threads,1,0);
-
- #if defined( BI_PLAT_WIN32 )
-
- //------------------------------------------------
- //
- // WIN32
- //
- // Use OS call to close thread handle.
- //
-
- inline void InternalCloseHandle( TThread::THandle Handle )
- {
- ::CloseHandle(Handle);
- }
-
- //------------------------------------------------
- //
- // WIN32
- //
- // Use OS call to suspend thread.
- //
-
- inline DWORD InternalSuspendThread( TThread::THandle Handle )
- {
- return ::SuspendThread(Handle);
- }
-
- //------------------------------------------------
- //
- // WIN32
- //
- // Use OS call to suspend thread.
- //
-
- inline DWORD InternalResumeThread( TThread::THandle Handle )
- {
- return ::ResumeThread(Handle);
- }
-
- //------------------------------------------------
- //
- // WIN32
- //
- // Use OS call to wait for thread termination.
- //
-
- inline unsigned long InternalWaitForThread( TThread::THandle Handle,
- unsigned long timeout )
- {
- return ::WaitForSingleObject( Handle, timeout );
- }
-
- //------------------------------------------------
- //
- // WIN32
- //
- // Use OS call to get thread priority.
- //
-
- inline int InternalGetThreadPriority( TThread::THandle Handle )
- {
- return ::GetThreadPriority( Handle );
- }
-
- //------------------------------------------------
- //
- // WIN32
- //
- // Use OS call to set thread priority.
- //
-
- inline int InternalSetThreadPriority( TThread::THandle Handle, int pri )
- {
- return ::SetThreadPriority( Handle, pri );
- }
-
- #endif
-
- #if defined( BI_PLAT_OS2 )
-
- //------------------------------------------------
- //
- // OS/2
- //
- // Don't need to close the handle.
- //
- inline void InternalCloseHandle( TThread::THandle )
- {
- }
-
- //------------------------------------------------
- //
- // OS/2
- //
- // Use OS call to suspend thread.
- //
-
- inline ULONG InternalSuspendThread( TThread::THandle Handle )
- {
- return ::DosSuspendThread(Handle);
- }
-
- //------------------------------------------------
- //
- // OS/2
- //
- // Use OS call to suspend thread.
- //
-
- inline ULONG InternalResumeThread( TThread::THandle Handle )
- {
- return ::DosResumeThread(Handle);
- }
-
- //------------------------------------------------
- //
- // OS/2
- //
- // Use OS call to wait for thread termination.
- //
-
- inline ULONG InternalWaitForThread( TThread::THandle &Handle,
- unsigned long timeout )
- {
- return ::DosWaitThread( &Handle, timeout );
- }
-
- #endif
-
- //------------------------------------------------
- //
- // TThread constructors
- //
-
- TThread::TThread() :
- #if defined( BI_PLAT_WIN32 )
- ThreadId(0),
- #elif defined( BI_PLAT_OS2 )
- Priority(0),
- #endif
- Handle(0),
- Stat(Created),
- TerminationRequested(0)
- {
- }
-
- TThread::TThread( const TThread& ) :
- #if defined( BI_PLAT_WIN32 )
- ThreadId(0),
- #elif defined( BI_PLAT_OS2 )
- Priority(0),
- #endif
- Handle(0),
- Stat(Created),
- TerminationRequested(0)
- {
- }
-
- //------------------------------------------------
- //
- // TThread assignment operator
- //
- // Used when assigning derived objects. Attempting to
- // assign from a running object is an error, since the
- // data fields in the running object can be changing
- // asynchronously.
- //
-
- const TThread& TThread::operator = ( const TThread& thread )
- {
- switch( GetStatus() )
- {
- case Created:
- case Suspended:
- case Finished:
- {
- if( this != &thread )
- {
- Handle = 0;
- #if defined( BI_PLAT_WIN32 )
- ThreadId = 0;
- #elif defined( BI_PLAT_OS2 )
- Priority = 0;
- #endif
- Stat = Created;
- TerminationRequested = 0;
- }
- return *this;
- }
- default:
- throw ThreadError(ThreadError::AssignError);
- }
- }
-
- //------------------------------------------------
- //
- // TThread destructor
- //
- // If the thread hasn't finished, destroying its control
- // object is an error.
- //
-
- TThread::~TThread()
- {
- if( GetStatus() != Finished )
- throw ThreadError(ThreadError::DestroyBeforeExit);
- InternalCloseHandle(Handle);
- }
-
- //------------------------------------------------
- //
- // TThread::Start()
- //
- // Starts the thread executing. The actual call depends on the
- // operating system. After the system call we check status.
- //
-
- TThread::THandle TThread::Start()
- {
- #if defined( BI_PLAT_WIN32 )
- #if defined( __MT__ )
- Handle = (HANDLE)::_beginthreadNT( &TThread::Execute, 4096, this, 0, 0, &ThreadId );
- #else
- Handle = ::CreateThread( 0, 0, &TThread::Execute, this, 0, &ThreadId );
- #endif
- #else
- #if defined( __MT__ )
- Handle = ::_beginthread( &TThread::Execute, 4096, this );
- #else
- APIRET res =
- ::DosCreateThread( &Handle,
- (void (__syscall*)(unsigned long))&TThread::Execute,
- REINTERPRET_CAST(unsigned long,this),
- FALSE,
- 4000 );
- #endif
- #endif
-
- if( Handle != 0 )
- {
- TRACEX( Threads, 1, "Thread started [id:" << Handle << ']' );
- Stat = Running;
- }
- else
- {
- TRACEX(Threads, 2, "Thread failed to start" );
- Stat = Invalid;
- throw ThreadError(ThreadError::CreationFailure);
- }
-
- return Handle;
- }
-
- //------------------------------------------------
- //
- // TThread::Suspend()
- //
- // It's an error to try to suspend a thread that
- // hasn't been started or that has already terminated.
- //
-
- unsigned long TThread::Suspend()
- {
- switch( GetStatus() )
- {
- case Created:
- TRACEX( Threads, 2, "Illegal thread suspension [id:" << Handle << ']' );
- throw ThreadError(ThreadError::SuspendBeforeRun);
- case Finished:
- TRACEX( Threads, 2, "Illegal thread suspension [id:" << Handle << ']' );
- throw ThreadError(ThreadError::SuspendAfterExit);
- default:
- TRACEX( Threads, 0, "Thread suspended [id:" << Handle << ']' );
- Stat = Suspended;
- return InternalSuspendThread(Handle);
- }
- }
-
- //------------------------------------------------
- //
- // TThread::Resume()
- //
- // It's an error to try to resume a thread that hasn't
- // been suspended.
- //
-
- unsigned long TThread::Resume()
- {
- switch( GetStatus() )
- {
- case Created:
- TRACEX( Threads, 2, "Illegal thread resumption [id:" << Handle << ']' );
- throw ThreadError(ThreadError::ResumeBeforeRun);
- case Running:
- TRACEX( Threads, 2, "Illegal thread resumption [id:" << Handle << ']' );
- throw ThreadError(ThreadError::ResumeDuringRun);
- case Finished:
- throw ThreadError(ThreadError::ResumeAfterExit);
- default:
- TRACEX( Threads, 0, "Thread resumed [id:" << Handle << ']' );
- unsigned long res = InternalResumeThread(Handle);
- if( res == 0 )
- Stat = Running;
- return res;
- }
- }
-
- //------------------------------------------------
- //
- // TThread::Terminate()
- //
- // Mark the thread for termination.
- //
-
- void TThread::Terminate()
- {
- TRACEX( Threads, 1, "Thread termination requested [handle:" << Handle << ']' );
- TerminationRequested = 1;
- }
-
- //------------------------------------------------
- //
- // TThread::WaitForExit()
- //
- // Block until the thread terminates.
- //
- // IMPORTANT: the meaning of the 'timeout' parameter is
- // different for NT and OS/2. Under NT it specifies how long
- // to wait for termination. Under OS/2 it specifies whether
- // to wait or to return immediately if the thread hasn't
- // terminated.
- //
-
- unsigned long TThread::WaitForExit( unsigned long timeout )
- {
- TRACEX( Threads, 1, "Waiting for thread exit [id:" << Handle << ']' );
- if( Stat == Running )
- return ::InternalWaitForThread( Handle, timeout );
- else
- return -1;
- }
-
- //------------------------------------------------
- //
- // TThread::TerminateAndWait()
- //
- // See note for WaitForExit().
- //
-
- unsigned long TThread::TerminateAndWait( unsigned long timeout )
- {
- Terminate();
- return WaitForExit( timeout );
- }
-
- //------------------------------------------------
- //
- // TThread::SetPriority()
- //
- // Set the thread's priority.
- //
-
- int TThread::SetPriority( int pri )
- {
- TRACEX( Threads, 1, "Thread priority changed to " << pri << " [id:" << Handle << ']' );
- #if defined( BI_PLAT_WIN32 )
- return ::SetThreadPriority(Handle,pri);
- #else
-
- APIRET res = DosSetPriority( PRTYS_THREAD,
- PRTYC_NOCHANGE,
- pri-Priority,
- Handle );
- if( res != 0 )
- Priority = pri;
- return res;
- #endif
- }
-
- //------------------------------------------------
- //
- // TThread::Execute()
- //
- // Run the thread.
- //
-
- #if defined( __MT__ )
- void _USERENTRY TThread::Execute( void *thread )
- {
- STATIC_CAST(TThread*,thread)->Run();
- }
- #elif defined( BI_PLAT_WIN32 )
- unsigned long _stdcall TThread::Execute( void *thread )
- {
- return STATIC_CAST(TThread*,thread)->Run();
- }
- #else
- void __stdcall TThread::Execute( unsigned long thread )
- {
- REINTERPRET_CAST(TThread*,thread)->Run();
- }
- #endif
-
- //------------------------------------------------
- //
- // TThread::CheckStatus()
- //
- // Call only when Stat claims that the thread is Running.
- //
-
- #if defined( BI_PLAT_WIN32 )
- TThread::Status TThread::CheckStatus() const
- {
- DWORD ExitCode;
- ::GetExitCodeThread( Handle, &ExitCode );
- if( ExitCode == STILL_ACTIVE )
- return Running;
- else
- return Finished;
- }
- #elif defined( BI_PLAT_OS2 )
- TThread::Status TThread::CheckStatus() const
- {
- if( ::DosWaitThread( CONST_CAST(THandle *,&Handle), DCWW_NOWAIT ) == ERROR_THREAD_NOT_TERMINATED )
- return Running;
- else
- return Finished;
- }
- #endif
-
- //------------------------------------------------
- //
- // TThread::ThreadError constructor
- //
-
- TThread::ThreadError::ThreadError(ErrorType type) :
- xmsg(MakeString(type)),
- Type(type)
- {
- }
-
- //------------------------------------------------
- //
- // TThread::ThreadError::MakeString()
- //
- // Translates an error code into a string.
- //
-
- string TThread::ThreadError::MakeString(ErrorType type)
- {
- static char *Names[] =
- {
- "Suspend() before Run()",
- "Resume() before Run()",
- "Resume() during Run()",
- "Suspend() after Exit()",
- "Resume() after Exit()",
- "creation failure",
- "destroyed before Exit()",
- "illegal assignment"
- };
- string Msg;
- Msg.reserve(40);
- Msg = "Error[thread]: ";
- Msg += Names[type];
- return Msg;
- }
-
-